package com.ruoyi.CompareCoordinate.service.impl;

import com.ruoyi.CompareCoordinate.domain.CoordinateCompare;
import com.ruoyi.common.exception.FileMismatchException;
import org.apache.commons.io.IOUtils;
import org.springframework.web.multipart.MultipartFile;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class CompareCoordinate {

    /**
     * 入口：接收 zip → 返回总结果（所有机器人汇总）
     * 注：为了保持接口单一返回值，这里把多机器人结果封装到
     * CoordinateCompare 的 detail 里，实际前端会再拆成多 sheet
     */
    public static Map<String, Map<String, CoordinateCompare>> compareFolders(List<MultipartFile> theoryFiles, List<MultipartFile> actualFiles, double tolerance, int paramCount) throws Exception {

//        if (theoryFiles.size() != actualFiles.size()) {
//            throw new IllegalArgumentException("理论文件与实际文件数量不一致");
//        }
        Map<String, Map<String, CoordinateCompare>> result = new LinkedHashMap<>();
        List<String> unmatchedFiles = new ArrayList<>();
        Set<String> seen =new HashSet<>();

        for (MultipartFile f1 : theoryFiles) {
            String fileName = new java.io.File(f1.getOriginalFilename()).getName()
                                                                        .replace(".JBI","")
                                                                        .replaceAll("(?i)SPOT_","");
            if (!seen.add(fileName)) {
                unmatchedFiles.add("理论文件夹中存在重复文件：" + fileName);
            }

            for(int i = 0; i < actualFiles.size(); i++){
                MultipartFile f2 = actualFiles.get(i);

                if (!fileName.equals(new java.io.File(f2.getOriginalFilename()).getName()
                                                                               .replace(".JBI","")
                                                                               .replaceAll("(?i)SPOT_",""))) {
                    if(i==actualFiles.size()-1){
                        unmatchedFiles.add("未找到与理论文件匹配的实际文件：" + fileName);
                    }
                    continue;
                }else {
                    String text1 = IOUtils.toString(f1.getInputStream(), StandardCharsets.UTF_8);
                    String text2 = IOUtils.toString(f2.getInputStream(), StandardCharsets.UTF_8);

                    /* 全部焊点 */
                    Map<String, double[]> map1 = parse(text1, paramCount);
                    Map<String, double[]> map2 = parse(text2, paramCount);
                    CoordinateCompare all = buildCompare(map1, map2, tolerance,paramCount);
                    all.setType("全部");

                    /* 关键焊点 */
                    Map<String, Map<String, double[]>> temp1 = parse1(text1, map1);
                    Map<String, double[]> spot1 = new LinkedHashMap<>();
                    for (Map<String, double[]> inner : temp1.values()) {
                        spot1.putAll(inner);
                    }

                    Map<String, Map<String, double[]>> temp2 = parse1(text2, map2);
                    Map<String, double[]> spot2 = new LinkedHashMap<>();
                    for (Map<String, double[]> inner : temp2.values()) {
                        spot2.putAll(inner);
                    }

                    CoordinateCompare key = buildCompare(spot1, spot2, tolerance,paramCount);
                    Map<String,String> W1 = buildWtm2WeldMap(temp1);
                    Map<String,String> W2 = buildWtm2WeldMap(temp2);
                    for (CoordinateCompare.Row row : key.getDetail()){
                        String id = row.getId();
                        row.setWtm1(W1.get(id));
                        row.setWtm2(W2.get(id));
                    }
                    key.setType("关键");

                    Map<String, CoordinateCompare> item = new LinkedHashMap<>();
                    item.put("全部", all);
                    item.put("关键", key);
                    result.put(fileName, item);
                    break;
                }
            }
        }
        if (!unmatchedFiles.isEmpty()) {
            throw new FileMismatchException(unmatchedFiles);
        }
        return result;
    }


    private static CoordinateCompare buildCompare(Map<String, double[]> map1,Map<String, double[]> map2,double keyword, int paramCount) {
        Set<String> keys = new LinkedHashSet<>(map1.keySet());
        keys.retainAll(map2.keySet());

        List<CoordinateCompare.Row> detail = new ArrayList<>();
        int sameCnt = 0;
        for (String id : keys) {
            double[] a = map1.get(id);
            double[] b = map2.get(id);
            Object[] c = equalsXYZ(a, b, keyword);
            boolean same = (boolean)c[0];
            double[] diff = (double[]) c[1];

            // 动态取前 个偏差，不足补 "0"
            double[] d = new double[3];
            for (int i=0 ;i < 3; i++){
                d[i]=0;
            }
            for (int i = 0; i<paramCount && i < 3; i++) {
                d[i] = diff[i];
            }
            if (same) sameCnt++;
            detail.add(new CoordinateCompare.Row(
                    id,
                    a == null ? "" : toCsv(a),
                    b == null ? "" : toCsv(b),
                    d[0],
                    d[1],
                    d[2],
                    "0",
                    "0",
                    same
            ));
        }

        CoordinateCompare.Ratio ratio = new CoordinateCompare.Ratio();
        ratio.setTotal(keys.size());
        ratio.setSame(sameCnt);
        ratio.setRate(keys.size() == 0 ? 0.0 : (double) sameCnt / keys.size());

        CoordinateCompare dto = new CoordinateCompare();
        dto.setDetail(detail);
        dto.setRatio(ratio);
        return dto;
    }

    /* ---------- 私有工具 ---------- */

    private static Map<String, double[]> parse(String text,int number ) {
        return Arrays.stream(text.split("\\r?\\n"))
                .map(String::trim)
                .filter(l -> l.startsWith("C00"))
                .map(l -> l.split("=", 2))
                .filter(arr -> arr.length == 2)
                .collect(LinkedHashMap::new,
                        (m, arr) -> m.put(arr[0].trim(),
                                Arrays.stream(arr[1].split(","))
                                        .limit(number)
                                        .mapToDouble(s -> Double.parseDouble(s.trim()))
                                        .toArray()),
                        Map::putAll);
    }

    //关键焊点添加的方法
    private static Map<String,Map<String, double[]>> parse1(String text, Map<String, double[]> parse) {
        Map<String,Map<String, double[]>> result = new LinkedHashMap<>();
        String[] lines = text.split("\\r?\\n");
        String currentWeld = null;
        Set<String> wtmSet = new LinkedHashSet<>();
        int idx = 1;
        for (String line : lines){
            Map<String, double[]> result1 =new LinkedHashMap<>();
            line = line.trim();

            if (line.startsWith("'---")){
                Matcher m = Pattern.compile("'-+\\s+([^-].*?)\\s+-+").matcher(line);
                if (m.matches()) {
                    currentWeld = m.group(1).trim();
                } else {
                    System.out.println("正则匹配失败");
                }
                continue;
            }

            if (line.startsWith("SVSPOTMOV")){
                String[] parts = line.split("\\s+");
                if(parts.length >=2){
                    String cId = parts[1];
                    String WTM= Arrays.stream(parts)
                                      .filter(p -> p.startsWith("WTM="))
                                      .findFirst()
                                      .orElse("");
                    while(!wtmSet.add(WTM)){
                        WTM = WTM+ "(" + (idx++) + ")";
                    }
                    if (cId.startsWith("C00") && parse.containsKey(cId))
                    {
                        if (currentWeld != null){
                            result1.putIfAbsent(currentWeld,parse.get(cId));
                        }else {
                            result1.putIfAbsent(WTM,parse.get(cId));
                        }
                        result.putIfAbsent(WTM,result1);
                        currentWeld=null;
                    }
                }
            }
        }
        return result;
    }

    private static Object[] equalsXYZ(double[] a, double[] b, double tol) {
        if (a == null || b == null) return new Object[]{false, null};
        double[] diffs = new double[a.length];
        boolean ok = true;
        for (int i = 0; i <a.length; i++) {
            diffs[i]=Math.abs(a[i] - b[i]);
            if (Math.abs(a[i] - b[i]) > tol) ok = false;
        }
        return new Object[]{ok,diffs};
    }

    private static String toCsv(double[] arr) {
        return Arrays.stream(arr)
                .mapToObj(d -> String.format("%.4f", d))
                .collect(Collectors.joining(","));
    }

    private static Map<String, String> buildWtm2WeldMap(Map<String, Map<String, double[]>> raw) {
        Map<String,String> wtm2Weld = new LinkedHashMap<>();
        for (Map.Entry<String, Map<String, double[]>> e : raw.entrySet()){
            wtm2Weld.put(e.getValue().keySet().iterator().next(),e.getKey());
        }
        return wtm2Weld;
    }

}